# -*- coding: utf-8 -*-
"""
主控制器 - 企业级视频文件名处理系统
统一调配各个模块，实现完整的处理流水线

⏺ 使用示例总结

  基本使用方法：

  # 从目录树文件处理（最常用）
  python3 main.py --tree data/数据工厂20250914150954_目录树.txt --output results.xlsx

  # 处理样本数据（测试用）
  python3 main.py --tree data/数据工厂20250914150954_目录树.txt --output test.xlsx --sample 10

  # 输出CSV格式
  python3 main.py --tree data/数据工厂20250914150954_目录树.txt --output results.csv --format csv

  # 详细输出模式
  python3 main.py --tree data/数据工厂20250914150954_目录树.txt --output results.xlsx --verbose

  关于扩展名问题：

  正如演示所示，脚本在处理目录树文件时，故意移除了文件扩展名，这是在 file_utils.py:61 行：

作者: Claude
版本: 2.0.0  
创建时间: 2024-09-14
"""

import argparse
import os
import sys
from datetime import datetime
from pathlib import Path
from typing import List, Optional, Dict, Any

# 导入各个处理模块
try:
    # 相对导入（包模式）
    from .processors.cleaner import clean_single_filename, batch_clean_filenames
    from .processors.type_detector import detect_video_type, VideoType, get_detection_confidence
    from .processors.fc2_extractor import process_fc2_filename
    from .processors.censored_extractor import process_censored_filename
    from .processors.uncensored_extractor import process_uncensored_filename
    from .utils.file_utils import (
        read_directory_tree_file,
        read_file_list_from_text,
        scan_directory_for_videos,
        is_video_file
    )
    from .utils.excel_utils import (
        save_results_to_excel,
        export_to_csv,
        ProcessingResult
    )
except ImportError:
    # 绝对导入（脚本模式）
    from processors.cleaner import clean_single_filename, batch_clean_filenames
    from processors.type_detector import detect_video_type, VideoType, get_detection_confidence
    from processors.fc2_extractor import process_fc2_filename
    from processors.censored_extractor import process_censored_filename
    from processors.uncensored_extractor import process_uncensored_filename
    from utils.file_utils import (
        read_directory_tree_file,
        read_file_list_from_text,
        scan_directory_for_videos,
        is_video_file
    )
    from utils.excel_utils import (
        save_results_to_excel,
        export_to_csv,
        ProcessingResult
    )


class VideoProcessor:
    """
    视频文件名处理器 - 主控制器
    
    企业级设计，函数式编程风格，支持流水线扩展
    """

    def __init__(self):
        """初始化处理器"""
        self.results: List[ProcessingResult] = []
        self.stats = {
            'total_files': 0,
            'processed_files': 0,
            'valid_results': 0,
            'fc2_count': 0,
            'censored_count': 0,
            'uncensored_count': 0,
            'failed_count': 0,
            'start_time': None,
            'end_time': None
        }

    def process_single_video(self, filename: str) -> Optional[ProcessingResult]:
        """
        处理单个视频文件 - 完整流水线
        
        :param filename: 原始文件名
        :return: 处理结果或None
        """
        if not filename:
            return None

        try:
            # 步骤1: 分离文件名和扩展名，然后清理文件名
            # filename 现在包含扩展名（如 "video.mp4"）
            file_stem = Path(filename).stem  # 获取不含扩展名的文件名
            cleaned_name = clean_single_filename(file_stem)

            if not cleaned_name:
                return ProcessingResult(
                    original_filename=filename,
                    processed_filename=filename,
                    video_type="UNKNOWN",
                    extracted_id="",
                    is_valid=False,
                    cleaned_filename="",
                    error_message="文件名清理后为空",
                    correct_result=None
                )

            # 特殊处理：含有"流出"的文件不处理，保持原样
            if "流出" in cleaned_name:
                return ProcessingResult(
                    original_filename=filename,
                    processed_filename=cleaned_name.replace("-流出", ""),  # 移除流出后缀
                    video_type="CENSORED",  # 流出通常是有码类型
                    extracted_id=cleaned_name.replace("-流出", ""),
                    is_valid=True,
                    cleaned_filename=cleaned_name,
                    error_message=None,
                    correct_result=None,
                    metadata={"special_format": "流出"}
                )

            # 步骤2: 检测视频类型
            detected_type = detect_video_type(cleaned_name)
            confidence = get_detection_confidence(cleaned_name, detected_type)

            if detected_type == VideoType.UNKNOWN:
                return ProcessingResult(
                    original_filename=filename,
                    processed_filename=filename,
                    video_type="UNKNOWN",
                    extracted_id="",
                    is_valid=False,
                    cleaned_filename=cleaned_name,
                    error_message="无法识别视频类型",
                    correct_result=None
                )

            # 步骤3: 调用对应的专门提取器
            try:
                if detected_type == VideoType.FC2:
                    extractor_func = process_fc2_filename
                elif detected_type == VideoType.CENSORED:
                    extractor_func = process_censored_filename
                elif detected_type == VideoType.UNCENSORED:
                    extractor_func = process_uncensored_filename
                else:
                    raise ValueError(f"不支持的视频类型: {detected_type}")

                result = extractor_func(filename, cleaned_name)

                if result:
                    standardized_name, metadata = result
                    # 添加检测置信度到元数据
                    metadata['detection_confidence'] = confidence

                    return ProcessingResult(
                        original_filename=filename,
                        processed_filename=standardized_name,
                        video_type=detected_type.value,
                        extracted_id=metadata.get('extracted_id', ''),
                        has_subtitle=metadata.get('has_subtitle', False),
                        cd_number=metadata.get('cd_number'),
                        is_4k=metadata.get('is_4k', False),
                        is_valid=metadata.get('is_valid', True),
                        metadata=metadata,
                        cleaned_filename=cleaned_name,
                        error_message=None,
                        correct_result=None
                    )
                else:
                    # 提取器返回None，说明处理失败
                    return ProcessingResult(
                        original_filename=filename,
                        processed_filename=filename,
                        video_type=detected_type.value,
                        extracted_id="",
                        is_valid=False,
                        cleaned_filename=cleaned_name,
                        error_message=f"{detected_type.value}提取器处理失败",
                        correct_result=None
                    )

            except Exception as e:
                return ProcessingResult(
                    original_filename=filename,
                    processed_filename=filename,
                    video_type=detected_type.value,
                    extracted_id="",
                    is_valid=False,
                    cleaned_filename=cleaned_name,
                    error_message=f"{detected_type.value}提取器异常: {str(e)}",
                    correct_result=None
                )

        except Exception as e:
            print(f"错误: 处理文件 {filename} 时出现异常: {e}")
            return ProcessingResult(
                original_filename=filename,
                processed_filename=filename,
                video_type="ERROR",
                extracted_id="",
                is_valid=False,
                cleaned_filename="",
                error_message=str(e),
                correct_result=None
            )

    def batch_process_videos(self, filenames: List[str], show_progress: bool = True) -> List[ProcessingResult]:
        """
        批量处理视频文件 - 函数式流水线
        
        :param filenames: 文件名列表
        :param show_progress: 是否显示处理进度
        :return: 处理结果列表
        """
        self.stats['start_time'] = datetime.now()
        self.stats['total_files'] = len(filenames)

        results = []

        for idx, filename in enumerate(filenames, 1):
            if show_progress and idx % 10 == 0:
                print(f"处理进度: {idx}/{len(filenames)} ({idx / len(filenames) * 100:.1f}%)")

            result = self.process_single_video(filename)
            if result:
                results.append(result)
                self.stats['processed_files'] += 1

                # 更新统计信息
                if result.is_valid:
                    self.stats['valid_results'] += 1
                    if result.video_type == "FC2":
                        self.stats['fc2_count'] += 1
                    elif result.video_type == "CENSORED":
                        self.stats['censored_count'] += 1
                    elif result.video_type == "UNCENSORED":
                        self.stats['uncensored_count'] += 1
                else:
                    self.stats['failed_count'] += 1

        self.stats['end_time'] = datetime.now()
        self.results = results

        if show_progress:
            self.print_processing_summary()

        return results

    def process_from_tree_file(self, tree_file_path: str, sample_size: Optional[int] = None) -> List[ProcessingResult]:
        """
        从目录树文件处理视频
        
        :param tree_file_path: 目录树文件路径
        :param sample_size: 样本大小（None表示处理全部）
        :return: 处理结果列表
        """
        print(f"从目录树文件读取: {tree_file_path}")

        try:
            filenames = read_directory_tree_file(tree_file_path)
            print(f"提取到 {len(filenames)} 个视频文件")

            if sample_size and sample_size < len(filenames):
                filenames = filenames[:sample_size]
                print(f"处理前 {sample_size} 个文件作为样本")

            return self.batch_process_videos(filenames)

        except Exception as e:
            print(f"错误: 处理目录树文件失败: {e}")
            return []

    def process_from_file_list(self, file_list_path: str) -> List[ProcessingResult]:
        """
        从文件列表处理视频
        
        :param file_list_path: 文件列表路径
        :return: 处理结果列表
        """
        print(f"从文件列表读取: {file_list_path}")

        try:
            filenames = read_file_list_from_text(file_list_path)
            print(f"读取到 {len(filenames)} 个视频文件")

            return self.batch_process_videos(filenames)

        except Exception as e:
            print(f"错误: 处理文件列表失败: {e}")
            return []

    def process_from_directory(self, directory_path: str, recursive: bool = False) -> List[ProcessingResult]:
        """
        从目录扫描处理视频
        
        :param directory_path: 目录路径
        :param recursive: 是否递归扫描
        :return: 处理结果列表
        """
        print(f"扫描目录: {directory_path}")

        try:
            filenames = scan_directory_for_videos(directory_path, recursive)
            print(f"发现 {len(filenames)} 个视频文件")

            return self.batch_process_videos(filenames)

        except Exception as e:
            print(f"错误: 扫描目录失败: {e}")
            return []

    def filter_results(self,
                       video_type: Optional[str] = None,
                       has_subtitle: Optional[bool] = None,
                       is_4k: Optional[bool] = None,
                       valid_only: bool = True) -> List[ProcessingResult]:
        """
        筛选处理结果 - 函数式筛选
        
        :param video_type: 视频类型筛选
        :param has_subtitle: 字幕筛选
        :param is_4k: 4K筛选
        :param valid_only: 仅有效结果
        :return: 筛选后的结果
        """
        filtered_results = self.results

        # 应用各种筛选条件
        if valid_only:
            filtered_results = [r for r in filtered_results if r.is_valid]

        if video_type:
            filtered_results = [r for r in filtered_results if r.video_type == video_type.upper()]

        if has_subtitle is not None:
            filtered_results = [r for r in filtered_results if r.has_subtitle == has_subtitle]

        if is_4k is not None:
            filtered_results = [r for r in filtered_results if r.is_4k == is_4k]

        return filtered_results

    def save_results(self,
                     output_file: str,
                     format_type: str = "excel",
                     extended: bool = False,
                     include_summary: bool = True,
                     filtered_results: Optional[List[ProcessingResult]] = None) -> None:
        """
        保存处理结果，包括失败文件的记录
        
        :param output_file: 输出文件路径
        :param format_type: 输出格式 (excel/csv)
        :param extended: 是否使用扩展格式
        :param include_summary: 是否包含汇总
        :param filtered_results: 自定义结果列表
        """
        results_to_save = filtered_results if filtered_results is not None else self.results

        try:
            if format_type.lower() == "excel":
                save_results_to_excel(results_to_save, output_file, extended, include_summary)
            elif format_type.lower() == "csv":
                export_to_csv(results_to_save, output_file)
            else:
                raise ValueError(f"不支持的输出格式: {format_type}")

            # 保存失败文件记录
            self._save_failed_files(output_file)

        except Exception as e:
            print(f"错误: 保存结果失败: {e}")

    def _save_failed_files(self, main_output_file: str) -> None:
        """
        保存处理失败的文件列表
        
        :param main_output_file: 主输出文件路径，用于生成失败文件记录的路径
        """
        # 获取所有处理失败的结果
        failed_results = [r for r in self.results if not r.is_valid]

        if not failed_results:
            print("✅ 所有文件处理成功，无失败文件")
            return

        # 从成功文件路径中提取时间戳，保持一致
        success_filename = os.path.basename(main_output_file)
        # 假设成功文件格式是 success_YYYYMMDD_HHMMSS.ext
        if success_filename.startswith("success_"):
            timestamp_part = success_filename.split("_", 1)[1].rsplit(".", 1)[0]  # 提取时间戳部分
        else:
            # 如果不是预期格式，生成新的时间戳
            from datetime import datetime
            timestamp_part = datetime.now().strftime("%Y%m%d_%H%M%S")

        output_dir = os.path.dirname(main_output_file)
        failed_file_path = os.path.join(output_dir, f"fail_{timestamp_part}.txt")

        try:
            with open(failed_file_path, 'w', encoding='utf-8') as f:
                from datetime import datetime
                f.write(f"处理失败文件记录 - 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write(f"失败文件总数: {len(failed_results)}\n")
                f.write("=" * 80 + "\n\n")

                # 按失败原因分组
                error_groups = {}
                for result in failed_results:
                    error_msg = result.error_message or "未知错误"
                    if error_msg not in error_groups:
                        error_groups[error_msg] = []
                    error_groups[error_msg].append(result)

                # 输出分组的失败文件
                for error_msg, results in error_groups.items():
                    f.write(f"【错误类型】: {error_msg}\n")
                    f.write(f"【文件数量】: {len(results)}\n")
                    f.write("-" * 60 + "\n")
                    for i, result in enumerate(results, 1):
                        f.write(f"{i:3d}. {result.original_filename}\n")
                        if result.cleaned_filename != result.original_filename:
                            f.write(f"     清理后: {result.cleaned_filename}\n")
                    f.write("\n" + "=" * 60 + "\n\n")

                f.write("\n详细失败文件列表 (CSV格式):\n")
                f.write("原始文件名,清理后文件名,错误信息,正确结果\n")
                for result in failed_results:
                    correct_result = result.correct_result or ""
                    f.write(f'"{result.original_filename}","{result.cleaned_filename}","{result.error_message or "未知错误"}","{correct_result}"\n')

            print(f"⚠️  失败文件记录已保存到: {failed_file_path}")
            print(f"📊 失败文件总数: {len(failed_results)}")

            # 显示失败统计
            print("\n失败原因统计:")
            for error_msg, results in error_groups.items():
                print(f"  {error_msg}: {len(results)}个文件")

        except Exception as e:
            print(f"❌ 保存失败文件记录时出错: {e}")

    def print_processing_summary(self) -> None:
        """打印处理汇总信息"""
        stats = self.stats
        duration = (stats['end_time'] - stats['start_time']).total_seconds() if stats['start_time'] and stats['end_time'] else 0

        print("\n" + "=" * 50)
        print("处理汇总报告")
        print("=" * 50)
        print(f"总文件数: {stats['total_files']}")
        print(f"处理文件数: {stats['processed_files']}")
        print(f"成功处理: {stats['valid_results']}")
        print(f"处理失败: {stats['failed_count']}")
        print(f"处理用时: {duration:.2f}秒")
        print("\n按类型统计:")
        print(f"  FC2类型: {stats['fc2_count']}")
        print(f"  有码类型: {stats['censored_count']}")
        print(f"  无码类型: {stats['uncensored_count']}")

        if stats['valid_results'] > 0:
            print(f"\n成功率: {stats['valid_results'] / stats['processed_files'] * 100:.1f}%")

        print("=" * 50)

    def get_statistics(self) -> Dict[str, Any]:
        """获取统计信息"""
        return self.stats.copy()


def create_argument_parser() -> argparse.ArgumentParser:
    """
    创建命令行参数解析器
    
    :return: 参数解析器
    """
    parser = argparse.ArgumentParser(
        description="企业级视频文件名处理系统 v2.0",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例用法:
  python main.py --input data.txt --output results.xlsx
  python main.py --tree tree.txt --output results.xlsx --sample 100  
  python main.py --directory /path/to/videos --output results.xlsx --recursive
  python main.py --input data.txt --output results.csv --format csv
        """
    )

    # 输入选项（互斥）
    input_group = parser.add_mutually_exclusive_group(required=True)
    input_group.add_argument(
        "--input", "-i",
        help="输入文件列表文件路径"
    )
    input_group.add_argument(
        "--tree", "-t",
        help="目录树文件路径"
    )
    input_group.add_argument(
        "--directory", "-d",
        help="视频文件目录路径"
    )

    # 输出选项
    parser.add_argument(
        "--output", "-o",
        required=True,
        help="输出文件路径"
    )

    # 格式选项
    parser.add_argument(
        "--format", "-f",
        choices=["excel", "csv"],
        default="excel",
        help="输出格式 (默认: excel)"
    )

    # 处理选项
    parser.add_argument(
        "--sample", "-s",
        type=int,
        help="样本大小（仅处理前N个文件）"
    )

    parser.add_argument(
        "--recursive", "-r",
        action="store_true",
        help="递归扫描子目录（仅用于--directory）"
    )

    # 输出选项
    parser.add_argument(
        "--extended", "-e",
        action="store_true",
        help="使用扩展输出格式（包含更多详细信息）"
    )

    parser.add_argument(
        "--no-summary",
        action="store_true",
        help="不生成汇总表（仅用于Excel格式）"
    )

    # 筛选选项
    parser.add_argument(
        "--type",
        choices=["fc2", "censored", "uncensored"],
        help="筛选特定视频类型"
    )

    parser.add_argument(
        "--subtitle-only",
        action="store_true",
        help="仅包含有字幕的视频"
    )

    parser.add_argument(
        "--4k-only",
        action="store_true",
        help="仅包含4K视频"
    )

    # 调试选项
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="详细输出模式"
    )

    return parser


def main():
    """主函数 - 命令行入口点"""
    parser = create_argument_parser()
    args = parser.parse_args()

    print("=" * 60)
    print("企业级视频文件名处理系统 v2.0")
    print("作者: Claude | 函数式设计 | 可扩展架构")
    print("=" * 60)

    # 创建处理器
    processor = VideoProcessor()

    try:
        # 根据输入类型处理
        if args.input:
            results = processor.process_from_file_list(args.input)
        elif args.tree:
            results = processor.process_from_tree_file(args.tree, args.sample)
        elif args.directory:
            results = processor.process_from_directory(args.directory, args.recursive)
        else:
            print("错误: 必须指定输入源")
            sys.exit(1)

        if not results:
            print("警告: 没有处理结果")
            return

        # 应用筛选
        filtered_results = processor.filter_results(
            video_type=args.type,
            has_subtitle=args.subtitle_only if args.subtitle_only else None,
            is_4k=getattr(args, '4k_only', False) if getattr(args, '4k_only', False) else None,
            valid_only=True
        )

        if args.verbose:
            print(f"\n筛选后结果数量: {len(filtered_results)}")

        # 生成成功文件的时间戳文件名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

        # 获取原始文件的扩展名
        original_ext = Path(args.output).suffix or ".xlsx"
        success_filename = f"success_{timestamp}{original_ext}"

        # 确保输出目录存在
        if not os.path.isabs(args.output):
            # 如果是相对路径，放在result目录下
            result_dir = os.path.join(os.path.dirname(__file__), "result")
            os.makedirs(result_dir, exist_ok=True)
            output_path = os.path.join(result_dir, success_filename)
        else:
            output_dir = os.path.dirname(args.output)
            output_path = os.path.join(output_dir, success_filename)

        # 保存结果
        processor.save_results(
            output_file=output_path,
            format_type=args.format,
            extended=args.extended,
            include_summary=not args.no_summary,
            filtered_results=filtered_results
        )

        # 显示处理结果统计
        total_results = len(processor.results)
        successful_results = len([r for r in processor.results if r.is_valid])
        failed_results = len([r for r in processor.results if not r.is_valid])

        print(f"\n📋 处理完成! 输出文件: {output_path}")
        print(f"📊 处理统计:")
        print(f"   总文件数: {total_results}")
        print(f"   成功处理: {successful_results}")
        print(f"   处理失败: {failed_results}")
        if total_results > 0:
            success_rate = (successful_results / total_results) * 100
            print(f"   成功率: {success_rate:.1f}%")

        if failed_results > 0:
            print(f"\n⚠️  注意: 有 {failed_results} 个文件处理失败，详细信息已保存到失败文件记录中")

    except KeyboardInterrupt:
        print("\n\n用户中断处理")
        sys.exit(1)
    except Exception as e:
        print(f"\n错误: 处理过程中出现异常: {e}")
        if args.verbose:
            import traceback
            traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    main()
